package com.formulas.component.extension;

import com.formulas.component.extension.register.AbstractComponentExecutor;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 扩展点执行器
 * @author yiwannuofulasi
 * @date 2023/6/12 17:43
 */
@Component
public class ExtensionExecutor extends AbstractComponentExecutor {

    private final Logger logger = LoggerFactory.getLogger(ExtensionExecutor.class);

    @Resource
    private ExtensionRepository extensionRepository;

    @Override
    protected <C> C locateComponent(Class<C> targetClz, BizScenario bizScenario) {
        C extension = locateExtension(targetClz, bizScenario);
        logger.debug("[Located Extension]: " + extension.getClass().getSimpleName());
        return extension;
    }

    /**
     * 获取扩展点对象
     * 如果业务场景唯一标识是 "天猫.提交订单.贵宾"
     *
     * 搜索路径如下: “天猫.提交订单.贵宾”;
     *             "天猫.提交订单.#defaultScenario#";
     *             “天猫.#defaultUseCase#.#defaultScenario#”
     * @param targetClz 查找目标
     */
    protected <Ext> Ext locateExtension(Class<Ext> targetClz, BizScenario bizScenario) {
        checkNull(bizScenario);

        Ext extension;

        logger.debug("BizScenario in locateExtension is : " + bizScenario.getUniqueIdentity());

        // 首先尝试使用完整的命名空间: “天猫.提交订单.贵宾”
        extension = firstTry(targetClz, bizScenario);
        if (extension != null) {
            return extension;
        }

        // 第二次尝试使用默认场景："天猫.提交订单.#defaultScenario#"
        extension = secondTry(targetClz, bizScenario);
        if (extension != null) {
            return extension;
        }

        // 第三次尝试使用默认用例+默认场景: “天猫.#defaultUseCase#.#defaultScenario#”
        extension = defaultUseCaseTry(targetClz, bizScenario);
        if (extension != null) {
            return extension;
        }

        throw new RuntimeException("不能找到其扩展点 for : "+targetClz+" 业务场景唯一标记:"+bizScenario.getUniqueIdentity());
    }

    /**
     * 首先尝试使用完整的命名空间: “天猫.提交订单.贵宾”
     *
     */
    private  <Ext> Ext firstTry(Class<Ext> targetClz, BizScenario bizScenario) {
        logger.debug("First trying with " + bizScenario.getUniqueIdentity());
        return locate(targetClz.getName(), bizScenario.getUniqueIdentity());
    }

    /**
     *  第二次尝试使用默认场景："天猫.提交订单.#defaultScenario#"
     *
     */
    private <Ext> Ext secondTry(Class<Ext> targetClz, BizScenario bizScenario){
        logger.debug("Second trying with " + bizScenario.getIdentityWithDefaultScenario());
        return locate(targetClz.getName(), bizScenario.getIdentityWithDefaultScenario());
    }

    /**
     * 第三次尝试使用默认用例+默认场景: “天猫.#defaultUseCase#.#defaultScenario#”
     *
     */
    private <Ext> Ext defaultUseCaseTry(Class<Ext> targetClz, BizScenario bizScenario){
        logger.debug("Third trying with " + bizScenario.getIdentityWithDefaultUseCase());
        return locate(targetClz.getName(), bizScenario.getIdentityWithDefaultUseCase());
    }

    /**
     * 根据查找目标类名称和业务场景唯一标记获取扩展点
     * @param name 查找目标类名称
     * @param uniqueIdentity 业务场景唯一标记
     * @return 从Map集合中获取扩展点
     * @param <Ext> 扩展点
     */
    private <Ext> Ext locate(String name, String uniqueIdentity) {
        final Ext ext = (Ext) extensionRepository.getExtensionRepo().
                get(new ExtensionCoordinate(name, uniqueIdentity));
        return ext;
    }

    /**
     * 校验业务场景对象是否为空则抛出异常
     * @param bizScenario 业务场景
     */
    private void checkNull(BizScenario bizScenario){
        if(bizScenario == null){
            throw new IllegalArgumentException("对于扩展业务场景（BizScenario）不能为空");
        }
    }
}
